package pcsr.simulator.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Hashtable;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import pcsr.simulator.control.ControlSimulatorEmitter;
import pcsr.simulator.control.ControlSimulatorSensor;
import pcsr.simulator.control.ControlSimulatorStructure;
import pcsr.simulator.control.ControlSimulatorWall;
import pcsr.simulator.control.ISimulatorStatusObserver;
import pcsr.simulator.control.RobotBrain;


public class SimulatorUIFrame extends JFrame implements ISimulatorStatusObserver {

	private static final long serialVersionUID = -8158933165251042465L;
	private RobotBrain robot;
	SimulationRobotField robotPanel;
	SimulationField wallsPanel;

	public static void main(String[] args) throws InterruptedException {

		LaunchSimulatorUI();

	}

	/**
	 * 
	 */
	public static void LaunchSimulatorUI() {
		// Create a JFrame, which is a Window with "decorations", i.e. 
		// title, border and close-button
		SimulatorUIFrame f = new SimulatorUIFrame();

		// Set a simple Layout Manager that arranges the contained 
		// Components
		//f.setLayout(new FlowLayout());                

		// Set the default close operation for the window, or else the 
		// program won't exit when clicking close button
		//  (The default is HIDE_ON_CLOSE, which just makes the window
		//  invisible, and thus don't exit the app)
		f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

		// Set the visibility as true, thereby displaying it
		//f.setVisible(true);
		f.addWindowListener(
				new WindowAdapter() {
					public void windowClosing( WindowEvent e )
					{
						System.exit( 0 );
					}
				}
		);
	}

	@Override
	public void NotifyRobotChange(final ControlSimulatorStructure robot) {
		Runnable doWorkRunnable = new Runnable() {
		    public void run() 
		    { 
		    	robotPanel.SetRobotPosition(robot.GetXPos(), robot.GetYPos());
		    	robotPanel.SetRobotAngle(robot.getRobotAngle());
		    	
		    	robotPanel.ClearSensorList();
		    	
		    	for(ControlSimulatorSensor s : robot.getSensors())
		    	{
			    	robotPanel.AddSensor(
			    			s.getSensorAngle(), 
			    			s.getSensorRange(), 
			    			new Point(s.GetXPos(), s.GetYPos())
			    			);
		    	}
		    	
		    	robotPanel.invalidate();
		    	robotPanel.getParent().repaint();
		    }
		};
		SwingUtilities.invokeLater(doWorkRunnable);
	}

	@Override
	public void NotifyWallsChange(final Hashtable<String, ControlSimulatorWall> walls) {
		Runnable doWorkRunnable = new Runnable() {
		    public void run() 
		    { 
		    	ArrayList<SimulatorWall> newWalls = new ArrayList<SimulatorWall>();
		    	
		    	for(ControlSimulatorWall w : walls.values())
		    	{
		    		SimulatorWall sw = new SimulatorWall();
		    		sw.setLocation(new Point(w.GetXPos(),w.GetYPos()));
		    		sw.setSize(w.GetWidth(), w.GetHeight());
		    		
		    		newWalls.add(sw);
		    	}
		    	wallsPanel.setWalls(newWalls);
		    	wallsPanel.invalidate();
		    	wallsPanel.getParent().repaint();
		    }
		};
		SwingUtilities.invokeLater(doWorkRunnable);
	}

	private void initialize() {
		this.setLayout(null);
		this.setPreferredSize(new Dimension(500, 500) );
		this.setSize(new Dimension(500, 500));
		this.getContentPane().setBackground(Color.BLUE);

		robotPanel = new SimulationRobotField();
		robotPanel.setLocation(30,30);
		robotPanel.setSize(400,400);
		robotPanel.setOpaque(false);
		this.add(robotPanel);
		
		wallsPanel = new SimulationField();
		wallsPanel.setLocation(30,30);
		wallsPanel.setSize(400,400);
		wallsPanel.setOpaque(true);	
		this.add(wallsPanel);
		
		
		// "Pack" the window, making it "just big enough".
		this.pack();	

		this.setVisible(true);

		this.setFocusable(true);
		
		robot.ObserveSimulatorStatus(this);
	}

	public SimulatorUIFrame()
	{
		super("PCSR Simulator");
		robot  = RobotBrain.GetInstance();
		initialize();
	}

	@Override
	public void NotifyEmittersChange(final Hashtable<String, ControlSimulatorEmitter> fieldEmitters) {
		Runnable doWorkRunnable = new Runnable() {
		    public void run() 
		    { 
		    	ArrayList<SimulatorEmitter> newEmitters = new ArrayList<SimulatorEmitter>();
		    	
		    	for(ControlSimulatorEmitter e : fieldEmitters.values())
		    	{
		    		SimulatorEmitter se = new SimulatorEmitter();
		    		se.setLocation(new Point(e.GetXPos(),e.GetYPos()));
		    		se.setSize(e.GetWidth(), e.GetHeight());
		    		
		    		newEmitters.add(se);
		    	}
		    	wallsPanel.setEmitters(newEmitters);
		    	wallsPanel.invalidate();
		    	wallsPanel.getParent().repaint();
		    }
		};
		SwingUtilities.invokeLater(doWorkRunnable);
	}
	
}


